#include <gmock/gmock.h> 

using ::testing::StrictMock;
using ::testing::_;
using ::testing::Return;

#include "QueryDataManipulation.hpp"

template<typename DataIterator, typename SelectType = DataIterator> class MockKernel : public QDM::IKernel<DataIterator, SelectType>
{
public:
	MOCK_CONST_METHOD2_T(where, void(ResultVector&, WhereFunction));
	MOCK_CONST_METHOD2_T(orderBy, void(ResultVector&, OrderByFunction));
	MOCK_CONST_METHOD3_T(select, void(const ResultVector&, SelectVector&, SelectFunction));
	MOCK_CONST_METHOD2_T(execute, void(ResultVector&, ExecuteFunction));
};

#define SIZEARRAY 10

class QDMTest : public ::testing::Test
{
protected:
	QDMTest() : _query(&_kernel){}

	void SetUp()
	{
		fillArray();
	}

	StrictMock<MockKernel<int*, float> > _kernel;
	QDM::QueryDataManipulation<int*, float> _query;

	int _array[SIZEARRAY];

private:
	void fillArray()
	{
		for (int i = 0; i < SIZEARRAY; i++)
		{
			_array[i] = i;
		}
	}
};

TEST_F(QDMTest, isCallsWhileSelect)
{
	EXPECT_CALL(_kernel, where(_, _));
	EXPECT_CALL(_kernel, orderBy(_, _));
	EXPECT_CALL(_kernel, select(_, _, _));

	std::vector<float> checkSelectType =
		_query.from(_array, _array + SIZEARRAY)
		.where([](int* item){return true;})
		.orderBy([](int* item1, int* item2){return true;})
		.select([](int* item){return (float)(*item);});
}

TEST_F(QDMTest, isCallsWhileExecute)
{
	EXPECT_CALL(_kernel, where(_, _));
	EXPECT_CALL(_kernel, orderBy(_, _));
	EXPECT_CALL(_kernel, execute(_, _));

	_query.from(_array, _array + SIZEARRAY)
		.where([](int* item){return true;})
		.orderBy([](int* item1, int* item2){return true;})
		.execute([](std::vector<int*>&, int){});
}

int main(int argc, char** argv)
{
	testing::InitGoogleTest(&argc, argv);
	RUN_ALL_TESTS();
	std::getchar();
}